#include <iostream>
#include <string>
#include "Logger.hpp"
#include <sstream>
#include <unordered_map>
#include <fstream>

static std::string sep = "\r\n";
static std::string sep1 = " ";
static std::string sep2 = ":";
static std::string wwwroot = "./wwwroot";
static std::string defaulthoom = "index.html";
static std::string html_404 = "./wwwroot/404.html";

static const std::string linesep = "\r\n";
static const std::string innersep1 = " ";
static const std::string innersep2 = ": ";
static const std::string argssep = "?";
class HttpRequst
{
private:
    std::string ReadOneLine(std::string &reqstr, bool *status)
    {
        auto pos = reqstr.find(sep);
        if (pos == std::string::npos)
        {
            *status = false;
            return std::string();
        }
        *status = true;
        auto line = reqstr.substr(0, pos);
        reqstr.erase(0, pos + sep.size());
        return line;
    }
    void BuitKV(std::string &Line, std::string *k, std::string *v)
    {
        auto pos = Line.find(sep2);
        if (pos == std::string::npos)
        {
            return;
        }
        *k = Line.substr(0, pos);
        *v = Line.substr(pos + sep2.size());
    }

public:
    HttpRequst() {}
    std::string Serialize(std::string &inbuffer)
    {
        // 不用做
        return "";
    }
    bool DSerialize(std::string &outbuffer)
    {
        LOG(LogLevel::DEBUG) << "###########测试反序例化";
        bool flag = true;
        std::string OneLine = ReadOneLine(outbuffer, &flag);
        LOG(LogLevel::DEBUG) << OneLine;
        if (!flag)
        {
            return false;
        }
        std::stringstream ss(OneLine); // 这个以空格为分隔符进行输入
        ss >> _method >> _uri >> _httpvesion;
        while (true)
        {
            flag = true;
            std::string Line = ReadOneLine(outbuffer, &flag);
            if (!Line.empty() && flag)
            {
                // 这里有一个k，v
                std::string k, v;
                BuitKV(Line, &k, &v);
                if (k.empty() || v.empty())
                {
                    continue;
                }
                _kv.insert({k, v});
            }
            else if (flag)
            {
                _black_line = Line;
                break;
            }
            else
            {
                return false;
            }
        }
        _path = wwwroot;
        _path += _uri; //./wwwroot
        if (_uri == "/")
        {
            _path += defaulthoom; // ./wwwroot/index.html
        }
        //这里面对URL做解析，分出？之后的内容，放到正文里面，之前的内容放到——path里面
        if(_method=="GET")
        {
            auto pos=_path.find(argssep);
            if(pos!=std::string::npos)
            {
                _req_bady=_path.substr(pos+argssep.size());
                _path=_path.substr(0,pos);
            }
        }
        else if (_method == "POST")
        {
            _req_bady =outbuffer ;
        }
  
        LOG(LogLevel::DEBUG) << _path;

        return true;
    }
    std::string path()
    {
        return _path;
    }
    std::string FindType()
    {
        if (_path.empty())
        {
            return std::string();
        }
        auto pos = _path.rfind(".");
        if (pos == std::string::npos)
        {
            return std::string();
        }
        std::string type = _path.substr(pos);
        return type;
    }
    void setpath(std::string path)
    {
        path = _path;
    }
    ~HttpRequst() {}

private:
    std::string _method;
    std::string _uri;
    std::string _httpvesion;
    std::unordered_map<std::string, std::string> _kv;
    std::string _black_line;
    std::string _req_bady;

    std::string _path; // 我们要访问资源的路径
};
class HttpResponce
{

private:
    std::string Code2desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
        case 404:
            return "Not found";
        default:
            break;
        }
        return "";
    }

public:
    HttpResponce()
        : _httpversion("HTTP/1.1"), _blank_line("\r\n") {

          };
    std::string Serialize(std::string &inbuffer)
    {
        std::string respstr = _httpversion + innersep1 + std::to_string(_code) +
                              innersep1 + _desc + linesep;

        for (auto &elem : _resp_headers)
        {
            std::string line = elem.first + innersep2 + elem.second + linesep;
            respstr += line;
        }
        respstr += _blank_line;

        respstr += _resp_body;

        return respstr;
    }

    bool read(std::string path)
    {
        // 以二进制的方式读取
        std::ifstream file(path, std::ios::binary);
        if (!file.is_open())
        {
            LOG(LogLevel::WARNING) << path << " 资源不存在!";
            return false;
        }

        // 定位到文件末尾获取文件大小
        file.seekg(0, std::ios::end);
        std::streampos fileSize = file.tellg(); // 获取文件大小
        file.seekg(0, std::ios::beg);

        // 创建足够大的字符串来保存数据
        _resp_body.resize(static_cast<size_t>(fileSize));

        // 读取文件内容到字符串
        file.read(&_resp_body[0], fileSize);
        file.close();

        return true;
    }
    void setcode(int code)
    {
        _code = code;
        _desc = Code2desc(code);
    }
    bool steheaders(std::string k, std::string &v)
    {
        _resp_headers[k] = v;
        return true;
    }

    ~HttpResponce() {};

private:
    std::string _httpversion;
    int _code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _resp_headers;
    std::string _blank_line;
    std::string _resp_body;
};
using handler = std::function<HttpResponce>(HttpRequst &);
class Http
{
private:
    std::unordered_map<std::string,handler> _handlers; // 这个是处理发放，可以在Main.cc里面添加方法
public:
    Http() {};
    std::string Suffix2Desc(const std::string &suffix)
    {
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".css")
            return "text/css";
        else if (suffix == ".js")
            return "application/x-javascript";
        else if (suffix == ".png")
            return "image/png";
        else if (suffix == ".jpg")
            return "image/jpeg";
        else if (suffix == ".txt")
            return "text/plain";
        else
            return "text/html";
    }
    std::string HttpDserialize(std::string &req)
    {
        HttpRequst requst;
        std::string send;
        if (requst.DSerialize(req))
        {
            HttpResponce resp;
            std::string path = requst.path(); // 我们可以获取资源的路径
                                              // 然后读取里面的内容，创建应答。
            // 这是是交互式的处理
            if (_handlers.find(path) != _handlers.end())
            {
                // 这里需要执行函数
            }
            else
            {
                if (resp.read(path))
                {
                    resp.setcode(200);
                }
                else
                {
                    resp.read(html_404);
                    requst.setpath(html_404);
                    std::string Type = requst.FindType();
                    std::string repType = Suffix2Desc(Type);
                    resp.steheaders("Content-Type", repType);
                    resp.setcode(404);
                }
                send = resp.Serialize(req);
            }

            // std::cout<<send;
        }
        return send;
    }

    ~Http() {};
};
